#include "ASpect.h"
#include "Timer.h"
#include <iostream>

using std::cout;
using std::endl;

struct TimeElapsedAspect
{
    void Before(int i)
    {
        m_lastTime = m_t.elapsed();
    }
    void After(int i)
    {
        cout << "time elapsed: " << m_t.elapsed() - m_lastTime << endl;
    }

private:
    double m_lastTime;
    Timer m_t;
};
struct LoggingAspect
{
    void Before(int i)
    {
        std::cout << "entering" << std::endl;
    }
    void After(int i)
    {
        std::cout << "leaving" << std::endl;
    } //注释即报错 ：‘struct LoggingAspect’ has no member named ‘After’
};
void foo(int a)
{
    cout << "real HT function: " << a << endl;
}

struct MyStruct
{
    // void foo() {}
    void foo(int) {}
    // void foo(double) {}
};

struct ASpect_1
{
    void Before(int i)
    {
        std::cout << "ASpect_1"
                  << "  entering" << std::endl;
    }
    void After(int i)
    {
        std::cout << "ASpect_1"
                  << " leaving" << std::endl;
    }
};

struct ASpect_2
{
    void Before(int i)
    {
        std::cout << "ASpect_2"
                  << "  entering" << std::endl;
    }
    void After(int i)
    {
        std::cout << "ASpect_2"
                  << " leaving" << std::endl;
    }
};

struct ASpect_3
{
    void After(int i)
    {
        std::cout << "ASpect_3"
                  << " leaving" << std::endl;
    }
};

struct ASpect_4
{
    void Before(int i)
    {
        std::cout << "ASpect_4"
                  << "  entering" << std::endl;
    }
};

int main()
{

    // cout << has_member_foo<MyStruct>::value << endl;         //判断是否存在无参的foo函数
    // cout << has_member_foo<MyStruct, double>::value << endl; //判断是否存在含int参数的foo函数
    // cout << "-----------------------" << endl;

    // //A K B  预处理A 核心逻辑 预处理B
    // Invoke<LoggingAspect, TimeElapsedAspect>(&foo, 1); //织入方法
    // cout << "-----------------------" << endl;

    Invoke<ASpect_1, ASpect_2>(&foo, 1); //before1 before2 核心逻辑 after1 after2
    cout << "-----------------------" << endl;
    Invoke<ASpect_2, ASpect_1>(&foo, 3); //before2 before1 核心逻辑 after2 after1
    cout << "-----------------------" << endl;
    Invoke<ASpect_3>(&foo, 2); //先处理切面逻辑，再处理核心逻辑
    cout << "-----------------------" << endl;
    Invoke<ASpect_4>(&foo, 5); //先处理核心逻辑，再处理切面

    return 0;
}
